<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>聊天室</title>
    <meta content="width=device-width, initial-scale=1.0" name="viewport">
    <link href="css/style-2.css" rel="stylesheet">
</head>
<body>

<div class="container">
    <h1>聊天</h1>
    <div id="chat-window">
        <!-- 聊天消息会动态添加到此处 -->
    </div>
    <div id="message-form">
        <input id="message" placeholder="输入你的消息" type="text">
        <button class="btn" id="btn" onclick="sendMsg()">发送</button>
    </div>
</div>

<script src="js/sockjs.min.js" type="text/javascript"></script>
<script src="js/stomp.umd.min.js" type="text/javascript"></script>
<script>
    // 获取当前的连接是http还是https
    const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
    const url = protocol + window.location.host + '/chat';
    const client = new StompJs.Client({
        brokerURL: url,
        debug: function (str) {
            console.log(str);
        },
    });
    // 如果浏览器里没有内置WebSocket
    if (typeof WebSocket !== 'function') {
        // webSocketFactory优先级比brokerURL高，可实现链接切换的效果
        client.webSocketFactory = function () {
            // 使用SockJS
            return new SockJS('/chat');
        };
    }
    // 连接成功后该干嘛
    client.onConnect = function () {
        listen();
    };
    // 连接失败该干嘛
    client.onStompError = function (frame) {
        console.log('错误报头: ' + frame.headers);
        console.log('其他信息: ' + frame.body);
    };
    // 启动连接,非主动断开会自动重连
    client.activate();

    // 获取消息显示框
    const chatWindow = document.querySelector('#chat-window');
    // 设置标记判断是否应该自动滚动
    let shouldScroll = true;
    // 监听消息框的滚动事件，如果用户手动滚动了消息框，则不再自动滚动
    chatWindow.addEventListener('scroll', function () {
        /**
         * scrollHeight（文档内容实际高度，包括超出视窗的溢出部分）、
         * scrollTop（滚动条滚动距离）、
         * clientHeight（窗口可视范围高度）。
         */
        const {scrollTop, scrollHeight, clientHeight} = chatWindow;
        // 因为浮点数的问题，拉到底部时 scrollTop + clientHeight 不一定>= scrollHeight
        shouldScroll = scrollTop + clientHeight >= (scrollHeight - 1);
    });

    // 持续监听服务端的消息，收到消息后执行回调函数
    function listen() {
        client.subscribe('/topic/chat', function (message) {
            console.log(message.body);
            const chatMessage = JSON.parse(message.body);
            // 格式化时间
            const time = new Date(chatMessage.time).toLocaleTimeString();
            // 从名称为userName的Cookie中获取用户名
            const userName = document.cookie.split('; ').find(row => row.startsWith('userName=')).split('=')[1];
            const chatMessageElement = document.createElement('div');
            chatMessageElement.classList.add('message'
                , chatMessage.from === userName ? 'sent' : 'received');
            chatMessageElement.innerHTML = `
            <span class="from">${chatMessage.from}</span>
            <span class="time">${time}</span>
            <p>${chatMessage.msg}</p>`;
            chatWindow.appendChild(chatMessageElement);
            // 如果应该自动滚动，则滚动到底部
            if (shouldScroll) {
                chatWindow.scrollTop = chatWindow.scrollHeight;
            }
        });
    }

    // 获取输入框
    const messageInput = document.querySelector('#message');
    // 按下回车键发送消息
    messageInput.addEventListener("keyup", function (event) {
        event.preventDefault();
        if (event.keyCode === 13) {
            document.getElementById("btn").click();
        }
    })

    // 封装发送消息的函数
    function sendMsg() {
        const message = messageInput.value.trim();
        if (message !== '') {
            client.publish({
                destination: '/app/chat',
                body: JSON.stringify({"msg": message})
            });
            messageInput.value = '';
            // 发消息后允许自动滚动
            shouldScroll = true;
        }
    }
</script>
</body>
</html>
